namespace Legend.Autofac
{
    using System;
    using System.Threading;
    using global::Autofac;
    using global::Autofac.Builder;
    using Legend.Caching;
    using Legend.Threading;

    /// <summary>
    /// Registers needed Legend-types in an Autofac container
    /// and sets the container as the service locator inside Legend.
    /// </summary>
    public class LegendAutofacModule
            : Module
    {
        /// <summary>
        /// Override to add registrations to the container.
        /// </summary>
        /// <param name="builder">The builder.</param>
        protected override void Load(ContainerBuilder builder)
        {
            base.Load(builder);

            builder
                .Register<SystemTimeProvider>(() => DateTime.Now)
                .As<SystemTimeProvider>()
                .SingletonScoped();

            builder
                .Register(c => TimerAdapter.Factory)
                .As<TimerFactory>()
                .ExternallyOwned();

            builder
                .Register<ReaderWriterLockSlimFactory>()
                .As<ISynchronizationManagerFactory>()
                .SingletonScoped();

            builder
                .Register(c => new Scheduler(c.Resolve<TimerFactory>(), c.Resolve<ISynchronizationManagerFactory>().CreateSynchronizationManager(LockRecursionPolicy.SupportsRecursion), c.Resolve<SystemTimeProvider>()))
                .As<IScheduler>()
                .SingletonScoped();

            builder
                .Register<InMemoryCache>()
                .As<ICache>()
                .SingletonScoped();

            builder
                .Register<DefaultRandomNumberGenerator>()
                .As<IRandomNumberGenerator>()
                .SingletonScoped();
        }
    }
}
